package erp

import (
	"context"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"

	"mall/common/globalkey"
	"mall/common/moneyx"
	"mall/common/utils/pointy"
	"mall/service/backend/api/internal/logic/utils/parse"
	"mall/service/backend/api/internal/svc"
	"mall/service/backend/api/internal/types"
	"mall/service/backend/common/erp"
	"mall/service/product/rpc/productclient"

	// "github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type PushProductToErpLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// 推送商品到erp
func NewPushProductToErpLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PushProductToErpLogic {
	return &PushProductToErpLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *PushProductToErpLogic) PushProductToErp(req *types.PushProductToErpReq) (*types.BaseMsgResp, error) {
	page, pageSize := parse.ParsePageInfo(
		req.Current,
		req.PageSize,
		l.svcCtx.Config.Query.DefaultAmount,
		l.svcCtx.Config.Query.MaxAmount,
	)

	data, err := l.svcCtx.ProductRpc.BackendGetProductList(l.ctx, &productclient.ProductListReq{
		Page:      page,
		PageSize:  pageSize,
		Ids:       req.Ids,
		WithMeta:  pointy.GetPointer(uint32(1)),
		WithEntry: pointy.GetPointer(uint32(1)),
		WithAttr:  pointy.GetPointer(uint32(1)),
		WithSku:   pointy.GetPointer(uint32(1)),
	})
	if err != nil {
		logx.Errorw("PushProductToErp ProductRpc.BackendGetProductList err", logx.Field("detail", err.Error()))
		return nil, err
	}

	var items []map[string]any
	if len(data.List) > 0 {
		var ids []uint64
		for _, v := range data.List {
			if v.Title == nil || len(*v.Title) == 0 {
				continue
			}

			if v.Id != nil && *v.Id > 0 {
				ids = append(ids, *v.Id)
			}

			var brand string
			if len(v.Relations) > 0 {
				for _, m := range v.Relations {
					if m.Key != nil && m.Name != nil {
						switch *m.Key {
						case globalkey.ProductRelationNameBrand:
							brand = *m.Name
						}
					}
				}
			}

			var categoryId string
			if v.CategoryId != nil && *v.CategoryId > 0 {
				categoryId = strconv.FormatUint(*v.CategoryId, 10)
			}

			var createdAt string
			if v.CreatedAt != nil {
				createdAt = *v.CreatedAt
			}
			var updatedAt string
			if v.UpdatedAt != nil {
				updatedAt = *v.UpdatedAt
			}

			var imageUrl string
			if len(v.Media) > 0 {
				for _, m := range v.Media {
					if len(imageUrl) > 0 {
						break
					}

					if m.Url != nil && len(*m.Url) > 0 {
						imageUrl = *m.Url
					}
					if len(imageUrl) == 0 && m.Uri != nil && len(*m.Uri) > 0 {
						imageUrl = *m.Uri
					}
				}
			}

			var productCode string
			if v.ProductCode != nil {
				productCode = *v.ProductCode
			}

			var productId string
			if v.Id != nil && *v.Id > 0 {
				productId = strconv.FormatUint(*v.Id, 10)
			}

			var uri string
			if v.Uri != nil && len(*v.Uri) > 0 {
				uri = l.svcCtx.Config.NfsConf.SiteUrl + *v.Uri
			}

			var attrs []string
			if len(v.Attrs) > 0 {
				for _, attr := range v.Attrs {
					if attr.Name != nil && len(*attr.Name) > 0 && len(attr.Options) > 0 {
						var opts []string
						for _, opt := range attr.Options {
							if opt.Name != nil && len(*opt.Name) > 0 {
								opts = append(opts, *opt.Name)
							}
						}

						attrs = append(attrs, fmt.Sprintf("%s:%s", *attr.Name, strings.Join(opts, ",")))
					}
				}
			}

			var status uint32
			if v.Status != nil {
				switch int32(*v.Status) {
				case globalkey.PostStatusTrash:
					status = 0
				case globalkey.PostStatusPublish:
					status = 1
				default:
					status = 2
				}
			}

			var unit string
			if len(v.Meta) > 0 {
				for _, v := range v.Meta {
					if v.Key != nil && v.Value != nil {
						switch *v.Key {
						case "stockUnit":
							unit = *v.Value
						}
					}
				}
			}

			var skus []map[string]any
			if len(v.Skus) > 0 {
				for _, sku := range v.Skus {
					var skuAttrs []string
					if len(sku.Specs) > 0 {
						// logx.Infof("PushProductToErp sku.Specs : %+v ", sku.Specs)
						for _, spec := range sku.Specs {
							if spec.Label != nil && len(*spec.Label) > 0 && len(spec.Options) > 0 {
								var opts []string
								for _, opt := range spec.Options {
									if opt.Label != nil && len(*opt.Label) > 0 {
										opts = append(opts, *opt.Label)
									}
								}
								if len(opts) > 0 {
									skuAttrs = append(skuAttrs, fmt.Sprintf("%s:%s", *spec.Label, strings.Join(opts, ",")))
								}
							}
						}
					}

					var mediaUrl string
					if sku.MediaUrl != nil {
						mediaUrl = *sku.MediaUrl
					}

					var retailPrice float64
					if sku.RetailPrice != nil && len(*sku.RetailPrice) > 0 {
						if f, err := moneyx.ParseAmountToFloat(*sku.RetailPrice); err == nil {
							retailPrice = f
						}
					}

					var skuCode string
					if sku.SkuCode != nil {
						skuCode = *sku.SkuCode
					}

					var skuId string
					if sku.Id != nil && *sku.Id > 0 {
						skuId = strconv.FormatUint(*sku.Id, 10)
					}

					var weight float64
					if sku.Weight != nil && len(*sku.Weight) > 0 {
						if f, err := moneyx.ParseAmountToFloat(*sku.Weight); err == nil {
							weight = f
						}
					}

					skus = append(skus, map[string]any{
						"attributes": strings.Join(skuAttrs, ";"), // 属性：key1:value;key2:value;...以key:value的键值形式拼接，必须使用半角符 （不能为空）  string
						// "barcode" // 条码  string
						"create_time":  createdAt,   // 创建时间，格式:yyyy-MM-dd HH:mm:ss  string<date-time>
						"image_url":    mediaUrl,    // 规格图片连接 ，用于ERP图片展示  string
						"item_id":      productId,   // 第三方商品编号  string
						"modifiy_time": updatedAt,   // 最新修改时间，格式:yyyy-MM-dd HH:mm:ss  string<date-time>
						"price":        retailPrice, // 规格单价  number
						"quantity":     0,           // 规格库存  integer
						"sku_code":     skuCode,     // 外部规格编码，商家自己设定的规格编码, 尽量填写，ERP通过该编码区分商品  string
						"sku_id":       skuId,       // 第三方规格编号 （不能为空）  string
						"status":       status,      // 状态,0：已删除，1：在售，2：待售，仓库中  integer
						"weight":       weight,      // 重量  number
					})
				}
			}

			erpMap := map[string]any{
				"create_time": createdAt,                    // 创建时间，格式:yyyy-MM-dd HH:mm:ss  string<date-time>
				"item_id":     productId,                    // 第三方商品编号 （不能为空）  string
				"modify_time": updatedAt,                    // 最新修改时间，格式:yyyy-MM-dd HH:mm:ss  string<date-time>
				"shop_nick":   l.svcCtx.Config.Erp.ShopNick, // 在ERP中注册的卖家（店铺）昵称 （不能为空）  string
				"status":      status,                       // 状态,0：已删除，1：在售，2：待售，仓库中  integer
				"title":       *v.Title,                     // 商品标题 （不能为空）  string

				//"barcode"  // 条码  string
				"brand":       brand,       // 品牌  string
				"category_id": categoryId,  // 第三方商品类目编号  string
				"image_url":   imageUrl,    // 商品图片连接 ，用于ERP图片展示  string
				"item_code":   productCode, // 商家编码  string
				"item_url":    uri,         // 商品连接 ，用于ERP跳转到商场  string
				// "price":       0,                            // 价格，若无子规格，必填  number
				"properties": strings.Join(attrs, ";"), // 属性：key1:value;key2:value;...以key:value的键值形式拼接，必须使用半角符  string
				// "quantity":    0,                            // 库存，若无子规格，必填  integer
				"skus": skus, // 规格集，无规格商品不填  array[object]
				"unit": unit, // 单位  string
				// "weight"  // 重量  number
			}
			items = append(items, erpMap)
		}

		// logx.Infof("PushProductToErp items: %+v ", items)
		// [map[brand:宝格丽 category_id:19 create_time:2025-01-17 12:26:03 image_url:https://static.scentrobe.com/storage/images/fragrances/451/c7847c2273fc7eadb12fe68ca1c02627.jpg item_code:12345611 item_id:51 item_url:https://www.scentrobe.com/product/Acqua-di-Parma-Blu-Mediterraneo-Fico-di-Amalfi-2006 modify_time:2025-01-17 17:14:49 properties:包装~:瓶装 shop_nick:shop1820 skus:[map[attributes:适合人群~:普通人群（女士>）;容量:10ml barcode: create_time:2025-01-17 12:26:03 image_url: item_id:51 modify_time:2025-01-17 12:26:03 price:1 quantity:0 sku_code:1 sku_id:122 status:2 weight:1] map[attributes:适合人群~:普通人群（女士）;容量:20ml barcode: create_time:2025-01-17 12:26:03 image_url: item_id:51 modify_time:2025-01-17 12:26:03 price:1 quantity:0 sku_code:1 sku_id:123 status:2 weight:1] map[attributes:适合人群~:普通人群（女士）;容量:50ml barcode: create_time:2025-01-17 12:26:03 image_url: item_id:51 modify_time:2025-01-17 12:26:03 price:1 quantity:0 sku_code:1 sku_id:124 status:2 weight:1] map[attributes:适合人群~:女士;容量:10ml barcode: create_time:2025-01-17 12:26:03 image_url: item_id:51 modify_time:2025-01-17 12:26:03 price:1 quantity:0 sku_code:1 sku_id:125 status:2 weight:1] map[attributes:适合人群~:女士;容>量:20ml barcode: create_time:2025-01-17 12:26:03 image_url: item_id:51 modify_time:2025-01-17 12:26:03 price:1 quantity:0 sku_code:1 sku_id:126 status:2 weight:1] map[attributes:适合人群~:女士;容量:50ml barcode: create_time:2025-01-17 12:26:03 image_url: item_id:51 modify_time:2025-01-17 12:26:03 price:1 quantity:0 sku_code:1 sku_id:127 status:2 weight:1] map[attributes:适合人群~:男士;容量:10ml barcode: create_time:2025-01-17 12:26:03 image_url: item_id:51 modify_time:2025-01-17 12:26:03 price:1 quantity:0 sku_code:1 sku_id:128 status:2 weight:1] map[attributes:适合人群~:男士;容量:20ml barcode: create_time:2025-01-17 12:26:03 image_url: item_id:51 modify_time:2025-01-17 12:26:03 price:1 quantity:0 sku_code:1 sku_id:129 status:2 weight:1] map[attributes:适合人群~:男士;容量:50ml barcode: create_time:2025-01-17 12:26:03 image_url: item_id:51 modify_time:2025-01-17 12:26:03 price:1 quantity:0 sku_code:1 sku_id:130 status:2 weight:1]] status:2 title:帕尔玛之水 蓝色地中海-阿玛菲无花果, 2006 unit:]] ","level":"info"}

		res, err := json.Marshal(items)
		if err != nil {
			logx.Errorw("PushProductToErp json.Marshal err", logx.Field("detail", err.Error()))
			return nil, err
		}

		// 文档地址：https://open.hupun.com/api-doc/erp/b2c/items/open
		path := "/erp/b2c/items/open"
		erpClient := erp.NewErp(l.svcCtx.Config.Erp.AppKey, l.svcCtx.Config.Erp.Secret, l.svcCtx.Config.Erp.Url, path)
		err = erpClient.GetSign(map[string]string{
			"items": string(res),
		})
		if err != nil {
			logx.Errorw("PushProductToErp GetSign err", logx.Field("detail", err.Error()))
			return nil, err
		}

		_, err = erpClient.CallErpApi()
		if err != nil {
			logx.Errorw("PushProductToErp CallErpApi err", logx.Field("detail", err.Error()))
			return nil, err
		}

		_, err = l.svcCtx.ProductRpc.UpdateProduct(l.ctx, &productclient.ProductInfo{ // 标记为已同步（存储于 product meta）
			Ids:       ids,
			ShowStock: pointy.GetPointer(uint32(1)),
		})
		if err != nil {
			logx.Errorw("PushProductToErp UpdateProduct err", logx.Field("detail", err.Error()))
		}
	}

	return &types.BaseMsgResp{
		Success: true,
		Msg:     "推送商品至ERP成功",
		// Msg:     l.svcCtx.Trans.Trans(l.ctx, res.Msg),
	}, nil
}
